package core.hmxchen.log.aspect;

import core.hmxchen.log.LogFormatter;
import core.hmxchen.log.LogFormatterFactory;
import core.hmxchen.log.RequestLogFormatter;
import core.hmxchen.log.annotation.LogPrint;
import core.hmxchen.log.config.LogPrintProperties;
import core.hmxchen.log.entity.MethodInfo;
import core.hmxchen.log.enums.Level;
import core.hmxchen.log.enums.Position;
import core.hmxchen.log.enums.Print;
import core.hmxchen.log.handler.LogHandler;
import core.hmxchen.log.handler.MethodHandler;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * GetMappingPrintAspect
 * TODO
 *
 * @author hmxchen
 * @version v1.0.0
 * @date 2021/9/12 19:35
 */
@Aspect
@Slf4j
public class RequestPrintAspect {
    @Resource(type = LogPrintProperties.class)
    private LogPrintProperties logPrintProperties;


    @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.GetMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.DeleteMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PutMapping)"
    )
    public void logPrint() {
    }
    /**
     * 环绕
     * @param proceedingJoinPoint
     * @return
     */
    @Around("logPrint()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = null;
        Throwable throwable = null;
        Object[] args = proceedingJoinPoint.getArgs();
        long startTime = System.currentTimeMillis();
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            throwable = e;
        }
        long time = System.currentTimeMillis() - startTime;
        if (LogHandler.isEnable(log)&&logPrintProperties.isPrintRequest()) {
            //获取格式化实现类
            print((MethodSignature) proceedingJoinPoint.getSignature(),args,result + LogHandler.TIME_KEY + time,throwable);
        }
        if (throwable != null) {
            throw throwable;
        }
        return result;
    }
    public void print(MethodSignature signature, Object[] args, Object result, Throwable throwable) {
        RequestLogFormatter request = LogFormatterFactory.getRequestByName(logPrintProperties.getRequestLogImpl());
        Method method = signature.getMethod();
        String methodName = method.getName();
        MethodInfo methodInfo=null;
        String biz = methodName;
        String[] filterParamNames ={};
        Level level = Level.UNKNOWN.equals(logPrintProperties.getLevel())?Level.DEBUG:logPrintProperties.getLevel();
        Position position = logPrintProperties.getPosition();
        //如果该方法还被LogPrint注解
        //则获取value作为业务名称
        if(signature.getMethod().isAnnotationPresent(LogPrint.class)){
            LogPrint annotation = signature.getMethod().getAnnotation(LogPrint.class);
            if(!Level.UNKNOWN.equals(annotation.level())){
                level = annotation.level();
            }
            if(!Position.UNKNOWN.equals(annotation.position())){
                position = annotation.position();
            }
            biz = annotation.biz()!=""? annotation.biz():methodName;
            filterParamNames = annotation.paramFilter();
        }
        switch (position) {
            case ENABLED:
                methodInfo = MethodHandler.getMethodInfo(signature.getDeclaringTypeName(), methodName, signature.getParameterNames());
                break;
            default:
                methodInfo = MethodHandler.getMethodInfo(signature, MethodInfo.NATIVE_LINE_NUMBER);
        }
        request.format(log,level, biz, methodInfo,
                args, filterParamNames, result, throwable);
    }
}
